package net.loststone.ingestion;

import net.loststone.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;

class InfojobsSlurperService {

    boolean transactional = true

    HttpConnectionManager connectionManager

    def searchUri = "http://www.infojobs.net/busqueda_ofertas_resultados.cfm";

    def SITE = "infojobs";

    def province_map = [
        "A Coruña" : "28",
        "Álava" : "2",
        "Albacete" : "3",
        "Alicante" : "4",
        "Almería" : "5",
        "Asturias" : "6",
        "Ávila" : "7",
        "Badajoz" : "8",
        "Barcelona" : "9",
        "Burgos" : "10",
        "Cáceres" : "11",
        "Cádiz" : "12",
        "Cantabria" : "13",
        "Castellón" : "14",
        "Ceuta" : "15",
        "Ciudad Real" : "16",
        "Córdoba" : "17",
        "Cuenca" : "18",
        "Girona" : "19",
        "Granada" : "21",
        "Guadalajara" : "22",
        "Guipúzcoa" : "23",
        "Huelva" : "24",
        "Huesca" : "25",
        "Baleares" : "26",
        "Jaén" : "27",
        "La Rioja" : "29",
        "Las Palmas" : "20",
        "León" : "30",
        "Lleida" : "31",
        "Lugo" : "32",
        "Madrid" : "33",
        "Málaga" : "34",
        "Melilla" : "35",
        "Murcia" : "36",
        "Navarra" : "37",
        "Ourense" : "38",
        "Palencia" : "39",
        "Pontevedra" : "40",
        "Salamanca" : "41",
        "Santa Cruz de Tenerife" : "46",
        "Segovia" : "42",
        "Sevilla" : "43",
        "Soria" : "44",
        "Tarragona" : "45",
        "Teruel" : "47",
        "Toledo" : "48",
        "Valencia" : "49",
        "Valladolid" : "50",
        "Vizcaya" : "51",
        "Zamora" : "52",
        "Zaragoza" : "53"
    ];

    def slurp(params) {
        HttpClient client = new HttpClient(connectionManager);
        HttpMethod method = new PostMethod(searchUri);

        Town town = Town.findById(params.town_id);
        if (town == null) {
            throw NoSuchElementException("Town ${params.town_id} not found");
        }

        // If town, get the province that is allowed by Infojobs API.
        if (town.type == 'town') {
            town = town.parent;
        }


        def query = new NameValuePair[2];
        query[0] = new NameValuePair("of_provincia", province_map.get(town.name));
        query[1] = new NameValuePair("palabra", params.keywords);
        method.setRequestBody(query);

        def job_links = null
        try {
            def status = client.executeMethod(method);
            if (status == HttpStatus.SC_OK) {
                def stream = method.getResponseBodyAsStream();
                job_links = processJobsLinks(stream);
            }
            else {
                log.error("Something went bad when slurping the jobs list from ${searchUri} (${status})");
                throw new RuntimeException("Cannot slurp jobs list from ${searchUri} (${status})")
            }
        }
        finally {
            method.releaseConnection();
        }

        def jobs = [];
        job_links.each() { url ->
            def job = slurpJob(client, url);
            if (job != null) { jobs.add(job); }
        }
        return jobs;
    }

    def processJobsLinks = { stream ->
        def slurper = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser());
        def root = slurper.parse(stream);
        def nodes = root.'**'.findAll{it.@class.text() =='vacant'};
        log.debug("Found ${nodes.size()} vacants on Infojobs");

        def job_links = [];

        nodes.each() { outer ->
            def links = outer.'**'.findAll{ inner -> inner.@href =~ '.*infojobs.*' }
            links.each {inner ->
                job_links.add("http:" + inner.@href);
            }
        }

        return job_links;
    }

    def slurpJob(client, jobUri) {
        log.info("Slurping job offer from ${jobUri}}");

        HttpMethod method = new GetMethod(jobUri);

        def job = null
        
        try {
            def status = client.executeMethod(method);
            if (status == HttpStatus.SC_OK) {
                def stream = method.getResponseBodyAsStream();
                job = processJob(stream, jobUri);
            }
            else {
                log.error("Something went bad when slurping a job from ${jobUri} (${status})");
                return null;
            }
        }
        finally {
            method.releaseConnection();
        }
        
        return job;
    }
    
    def processJob = { stream, link ->
        def slurper = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser());
        def root = slurper.parse(stream);

        Job job = new Job(link : link, site: SITE);

        def name = root.'**'.find{it.@id.text() =='prefijoPuesto'};
        job.name = name.text();

        def descr = root.'**'.find{it.@id.text() =='prefijoDescripcion'};
        job.description = descr.text();

        def location = root.'**'.find{it.@id.text() =='prefijoPoblacion'};
        job.location = location.text();

        def company = root.'**'.find{it.@id.text() =='prefijoEmpresa'};
        job.company = company.text();

        def salary = root.'**'.find{it.@id.text() =='prefijoEmpresa'};
        job.salary = null; //salary.text();

        return job;
    }

}
